package com.tzbank.common.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.tzbank.common.constants.TzbConstants;
import com.tzbank.common.dao.FlowNodePageOptimizeMapper;
import com.tzbank.common.dao.FlowNodePageOptimizeRelationMapper;
import com.tzbank.common.dao.FlowOptimizeMapper;
import com.tzbank.common.dao.FlowOptimizeRelationMapper;
import com.tzbank.common.entity.FlowNodePageOptimize;
import com.tzbank.common.entity.FlowNodePageOptimizeRelation;
import com.tzbank.common.entity.FlowOptimize;
import com.tzbank.common.entity.FlowOptimizeRelation;
import com.tzbank.common.service.ProcessOptimizationService;
import com.tzbank.utils.CodeUtil;
import com.tzbank.utils.ResultUtil;

import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

@Slf4j
@Service
public class ProcessOptimizationServiceImpl implements ProcessOptimizationService {

	@Autowired
	private FlowOptimizeMapper flowOptimizeMapper;

	@Autowired
	private FlowOptimizeRelationMapper flowOptimizeRelationMapper;

	@Autowired
	private FlowNodePageOptimizeRelationMapper flowNodePageOptimizeRelationMapper;

	@Autowired
	private FlowNodePageOptimizeMapper flowNodePageOptimizeMapper;

	/**
	 * 节点优化
	 * @param jsonObject
	 * @return
	 * @author XUZONGTIAN 2018年5月17日
	 */
	private JSONObject nodeOptimization(JSONObject jsonObject) throws Exception {

		JSONObject paramsJSON = jsonObject.getJSONObject(TzbConstants.paramsJson);

		JSONObject flowJSON = jsonObject.getJSONObject(TzbConstants.flowJson);

		// flowset 规则数组
		JSONArray flowsetJsonArray = flowJSON.getJSONArray(TzbConstants.flowset);

		// 流程ID
		String flowId = flowsetJsonArray.getJSONObject(flowsetJsonArray.size() - 1).getString(TzbConstants.flowId);

		// 根据流程ID查询所有规则组合
		List<FlowOptimizeRelation> flowOptimizeRelations = this.flowOptimizeRelationMapper.selectByFlowId(flowId);
		// 如果查不到流程规则集，那么直接返回jsonObject
		if (flowOptimizeRelations.size() < 1) {
			log.info("流程ID{}下不存在规则 ", flowId);
			return jsonObject;
		}
		Iterator<FlowOptimizeRelation> optimizeRelationIterator = flowOptimizeRelations.iterator();

		// 用来存储将要删除的NODE--->JSON对象
		List<Object> deleteNodeItems = new ArrayList<Object>();

		// 遍历规则组合
		while (optimizeRelationIterator.hasNext()) {
			FlowOptimizeRelation flowOptimizeRelation = optimizeRelationIterator.next();
			log.info("FlowOptimizeRelation toString(): {}", flowOptimizeRelation.toString());

			// 规则未启用 跳过本次 执行下次循环
			if (!FlowOptimizeRelation.ENUM_STATUS.VALUE_1.val().equals(flowOptimizeRelation.getStatus())) {
				continue;
			}

			// 获取规则ID 多个规则为以逗号分割 *,*,*
			String flowRuleIds = flowOptimizeRelation.getFlowRuleIds();
			if (flowRuleIds.endsWith(",")) {
				flowRuleIds = flowRuleIds.substring(0, flowRuleIds.length() - 1);
			}
			flowRuleIds = "'" + flowRuleIds.replace(",", "','") + "'";

			// 定义Map 保存本次规则组合是否符合 Key = 规则名称 Value = true符合 : false不符合
			Map<String, Boolean> checkMap = new HashMap<String, Boolean>();

			// 查询规则实现 进行校验规则是否符合
			List<FlowOptimize> flowOptimizes = this.flowOptimizeMapper.selectByINFlowRuleId(flowRuleIds);

			Iterator<FlowOptimize> flowOptimizeIterator = flowOptimizes.iterator();

			// 遍历规则
			while (flowOptimizeIterator.hasNext()) {

				FlowOptimize flowOptimize = flowOptimizeIterator.next();
				log.info("FlowOptimize toString(): {}", flowOptimize.toString());

				// 遍历用户用户信息中的规则 校验是否匹配
				Iterator<String> transferJsonObjIterator = paramsJSON.keys();

				while (transferJsonObjIterator.hasNext()) {
					String key = transferJsonObjIterator.next();
					String value = paramsJSON.getString(key);

					if (!key.equals(flowOptimize.getRuleName())) {
						continue;
					}
					String rangeValue = flowOptimize.getRangeValue();
					String operator = flowOptimize.getOperator();
					String reg = "^[0-9]+(.[0-9]+)?$";
					// 判断输入参数和规则优化值都为数字时，根据操作符比较大小
					if (rangeValue.matches(reg) && value.matches(reg)) {
						BigDecimal intParamValue = new BigDecimal(rangeValue).setScale(2, BigDecimal.ROUND_HALF_UP);
						BigDecimal intVal = new BigDecimal(value).setScale(2, BigDecimal.ROUND_HALF_UP);

						// >
						if (FlowNodePageOptimize.ENUM_PARAMOPERATOR.VALUE_BIG.val().equals(operator)) {
							checkMap.put(key, intVal.doubleValue() > intParamValue.doubleValue());
						}

						// <
						if (FlowNodePageOptimize.ENUM_PARAMOPERATOR.VALUE_SMALL.val().equals(operator)) {
							checkMap.put(key, intVal.doubleValue() < intParamValue.doubleValue());
						}

						// ==
						if (FlowNodePageOptimize.ENUM_PARAMOPERATOR.VALUE_EQUAL.val().equals(operator)) {
							checkMap.put(key, intVal.doubleValue() == intParamValue.doubleValue());
						}

						// <>
						if (FlowNodePageOptimize.ENUM_PARAMOPERATOR.VALUE_NOT_EQUAL.val().equals(operator)) {
							checkMap.put(key, intVal.doubleValue() != intParamValue.doubleValue());
						}

						// >=
						if (FlowNodePageOptimize.ENUM_PARAMOPERATOR.VALUE_BIG_EQUAL.val().equals(operator)) {
							checkMap.put(key, intVal.doubleValue() >= intParamValue.doubleValue());
						}

						// <=
						if (FlowNodePageOptimize.ENUM_PARAMOPERATOR.VALUE_SMALL_EQUAL.val().equals(operator)) {
							checkMap.put(key, intVal.doubleValue() <= intParamValue.doubleValue());
						}

					} else {
						// 不是数字时，只需比较是否相等；KEY = 规则名称 VALUE = 表里配置的VALUE是否与用户信息中的VALUE相等
						checkMap.put(key, flowOptimize.getRangeValue().equals(value));
					}
				}

			}

			// 规则组合运算符 null,&&,||
			String ruleLogic = flowOptimizeRelation.getRuleLogic();

			// 删除的节点 *,*,*
			String[] removeFlowNodeArr = flowOptimizeRelation.getRemoveFlowNode().split(",");

			// 为null的情况 规则必须是单个 不能为组合 否则当做脏数据 不作处理;为true时才执行
			if (StringUtils.isEmpty(ruleLogic) && flowOptimizes.size() == 1 && checkMap.values().size() == flowOptimizes.size()) {
				if (checkMap.values().contains(true)) {
					for (int i = 0; i < removeFlowNodeArr.length; i++) {
						String removeFlowNode = removeFlowNodeArr[i];
						if (StringUtils.isEmpty(removeFlowNode)) {
							continue;
						}
						int index = Integer.parseInt(removeFlowNode);
						index--;
						deleteNodeItems.add(jsonObject.getJSONObject(TzbConstants.flowJson).getJSONArray(TzbConstants.flowset).get(index));
					}
				}
			}

			// 为||的情况 只要有一个规则符合即可 checkMap包含一个TRUE
			if (FlowOptimizeRelation.ENUM_RULELOGIC.VALUE_OR.val().equals(ruleLogic) && checkMap.values().size() == flowOptimizes.size()) {
				if (checkMap.values().contains(true)) {
					for (int i = 0; i < removeFlowNodeArr.length; i++) {
						String removeFlowNode = removeFlowNodeArr[i];
						if (StringUtils.isEmpty(removeFlowNode)) {
							continue;
						}
						int index = Integer.parseInt(removeFlowNode);
						index--;
						deleteNodeItems.add(jsonObject.getJSONObject(TzbConstants.flowJson).getJSONArray(TzbConstants.flowset).get(index));
					}
				}
			}

			// 为&&的情况 必须所有规则符合 checkMap中不能包含一个FALSE
			if (FlowOptimizeRelation.ENUM_RULELOGIC.VALUE_AND.val().equals(ruleLogic) && checkMap.values().size() == flowOptimizes.size()) {
				if (!checkMap.values().contains(false)) {
					for (int i = 0; i < removeFlowNodeArr.length; i++) {
						String removeFlowNode = removeFlowNodeArr[i];
						if (StringUtils.isEmpty(removeFlowNode)) {
							continue;
						}
						int index = Integer.parseInt(removeFlowNode);
						index--;
						deleteNodeItems.add(jsonObject.getJSONObject(TzbConstants.flowJson).getJSONArray(TzbConstants.flowset).get(index));
					}
				}
			}

		}

		if (0 < deleteNodeItems.size()) {
			jsonObject.getJSONObject(TzbConstants.flowJson).getJSONArray(TzbConstants.flowset).removeAll(deleteNodeItems);
		}

		return jsonObject;
	}

	/**
	 * 页面优化
	 * @param jsonObject
	 * @return
	 * @author XUZONGTIAN 2018年5月17日
	 */
	private JSONObject pageOptimization(JSONObject jsonObject) throws Exception {

		JSONObject paramsJSON = jsonObject.getJSONObject(TzbConstants.paramsJson);

		JSONObject flowJSON = jsonObject.getJSONObject(TzbConstants.flowJson);

		// flowset 规则数组
		JSONArray flowsetJsonArray = flowJSON.getJSONArray(TzbConstants.flowset);

		// 流程ID
		String flowId = flowsetJsonArray.getJSONObject(flowsetJsonArray.size() - 1).getString(TzbConstants.flowId);

		// 参数中的流程组
		Iterator<JSONObject> jsonObjectIterator = flowsetJsonArray.iterator();

		// 根据流程ID 查询所有节点规则组合
		List<FlowNodePageOptimizeRelation> flowNodePageOptimizeRelations = this.flowNodePageOptimizeRelationMapper.selectByFlowId(flowId);
		if (flowNodePageOptimizeRelations.size() < 1) {
			log.info("流程ID{}下不存在页面规则 ", flowId);
			return flowJSON;
		}

		Map<String, Boolean> checkMap = new HashMap<String, Boolean>();

		int jsonIndex = 0;

		Map<String, String> paramMap = new HashMap<>();

		// 遍历参数中的流程组
		while (jsonObjectIterator.hasNext()) {
			JSONObject jsonObj = jsonObjectIterator.next();
			String value = jsonObj.getString(TzbConstants.flowNode);

			// 遍历表里的规则组合
			Iterator<FlowNodePageOptimizeRelation> fnporIterator = flowNodePageOptimizeRelations.iterator();
			while (fnporIterator.hasNext()) {

				// 清空Map 准备工作
				paramMap.clear();
				checkMap.clear();

				FlowNodePageOptimizeRelation flowNodePageOptimizeRelation = fnporIterator.next();
				log.info("FlowNodePageOptimizeRelation toString(): {}", flowNodePageOptimizeRelation.toString());

				// 规则未启用 过滤本次
				if (!FlowNodePageOptimizeRelation.ENUM_STATUS.VALUE_1.val().equals(flowNodePageOptimizeRelation.getStatus())) {
					continue;
				}

				// 参数中的node <> 表里的node 过滤本次
				if (!value.equals(flowNodePageOptimizeRelation.getNodeId())) {
					continue;
				}

				// 获取规则ID 多个规则为以逗号分割 *,*,*
				String pageIds = flowNodePageOptimizeRelation.getPageIds();
				if (pageIds.endsWith(",")) {
					pageIds = pageIds.substring(0, pageIds.length() - 1);
				}

				// 拼接MYSQL IN 参数
				pageIds = "'" + pageIds.replace(",", "','") + "'";

				paramMap.put("flowId", flowId);
				paramMap.put("pageIds", pageIds);
				// 按照规则ID 查询规则
				List<FlowNodePageOptimize> flowNodePageOptimizes = this.flowNodePageOptimizeMapper.selectByInIds(paramMap);

				// 循环参数中用户信息所有配置项
				Iterator<String> strIterator = paramsJSON.keys();
				while (strIterator.hasNext()) {
					String key = strIterator.next();
					String val = paramsJSON.getString(key);

					// 循环规则
					Iterator<FlowNodePageOptimize> fnpoIterator = flowNodePageOptimizes.iterator();
					while (fnpoIterator.hasNext()) {
						FlowNodePageOptimize flowNodePageOptimize = fnpoIterator.next();
						log.info("FlowNodePageOptimize toString(): {}", flowNodePageOptimize.toString());

						String paramName = flowNodePageOptimize.getParamName();
						String paramOperator = flowNodePageOptimize.getParamOperator();
						String paramValue = flowNodePageOptimize.getParamValue();

						// 参数中用户key <> 表里的paramName 过滤本次
						if (!key.equals(paramName)) {
							continue;
						}

						BigDecimal intVal = new BigDecimal(val).setScale(2, BigDecimal.ROUND_HALF_UP);
						BigDecimal intParamValue = new BigDecimal(paramValue).setScale(2, BigDecimal.ROUND_HALF_UP);

						// >
						if (FlowNodePageOptimize.ENUM_PARAMOPERATOR.VALUE_BIG.val().equals(paramOperator)) {
							checkMap.put(key, intVal.doubleValue() > intParamValue.doubleValue());
						}

						// <
						if (FlowNodePageOptimize.ENUM_PARAMOPERATOR.VALUE_SMALL.val().equals(paramOperator)) {
							checkMap.put(key, intVal.doubleValue() < intParamValue.doubleValue());
						}

						// ==
						if (FlowNodePageOptimize.ENUM_PARAMOPERATOR.VALUE_EQUAL.val().equals(paramOperator)) {
							checkMap.put(key, intVal.doubleValue() == intParamValue.doubleValue());
						}

						// <>
						if (FlowNodePageOptimize.ENUM_PARAMOPERATOR.VALUE_NOT_EQUAL.val().equals(paramOperator)) {
							checkMap.put(key, intVal.doubleValue() != intParamValue.doubleValue());
						}

						// >=
						if (FlowNodePageOptimize.ENUM_PARAMOPERATOR.VALUE_BIG_EQUAL.val().equals(paramOperator)) {
							checkMap.put(key, intVal.doubleValue() >= intParamValue.doubleValue());
						}

						// <=
						if (FlowNodePageOptimize.ENUM_PARAMOPERATOR.VALUE_SMALL_EQUAL.val().equals(paramOperator)) {
							checkMap.put(key, intVal.doubleValue() <= intParamValue.doubleValue());
						}

					}

				}

				log.info("checkMap toString(): {}", checkMap.toString());

				// 规则组合运算符 null,&&,||
				String ruleLogic = flowNodePageOptimizeRelation.getRuleLogic();

				// 为null的情况 规则必须是单个 不能为组合 否则当做脏数据 不作处理
				if (StringUtils.isEmpty(ruleLogic) && flowNodePageOptimizes.size() == 1 && flowNodePageOptimizes.size() == checkMap.size()) {
					// 规则符合
					if (checkMap.values().contains(true)) {

						JSONObject jsonFlow = flowsetJsonArray.getJSONObject(jsonIndex);
						jsonFlow.put(TzbConstants.pageId, flowNodePageOptimizeRelation.getToPageId());
						jsonFlow.put(TzbConstants.pageName, flowNodePageOptimizeRelation.getToPageName());
						jsonFlow.put(TzbConstants.pageRouter, flowNodePageOptimizeRelation.getToPageRouter());

						jsonObject.getJSONObject(TzbConstants.flowJson).getJSONArray(TzbConstants.flowset).remove(jsonIndex);
						jsonObject.getJSONObject(TzbConstants.flowJson).getJSONArray(TzbConstants.flowset).add(jsonIndex, jsonFlow);
					}
				}

				// 为&&的情况 必须所有规则符合 checkMap中不能包含一个FALSE
				if (FlowNodePageOptimizeRelation.ENUM_RULELOGIC.VALUE_AND.val().equals(ruleLogic) && flowNodePageOptimizes.size() == checkMap.size()) {
					if (!checkMap.values().contains(false)) {
						JSONObject jsonFlow = flowsetJsonArray.getJSONObject(jsonIndex);
						jsonFlow.put(TzbConstants.pageId, flowNodePageOptimizeRelation.getToPageId());
						jsonFlow.put(TzbConstants.pageName, flowNodePageOptimizeRelation.getToPageName());
						jsonFlow.put(TzbConstants.pageRouter, flowNodePageOptimizeRelation.getToPageRouter());

						jsonObject.getJSONObject(TzbConstants.flowJson).getJSONArray(TzbConstants.flowset).remove(jsonIndex);
						jsonObject.getJSONObject(TzbConstants.flowJson).getJSONArray(TzbConstants.flowset).add(jsonIndex, jsonFlow);
					}
				}

				// 为||的情况 只要有一个规则符合即可 checkMap包含一个TRUE
				if (FlowNodePageOptimizeRelation.ENUM_RULELOGIC.VALUE_OR.val().equals(ruleLogic) && flowNodePageOptimizes.size() == checkMap.size()) {
					if (checkMap.values().contains(true)) {
						JSONObject jsonFlow = flowsetJsonArray.getJSONObject(jsonIndex);
						jsonFlow.put(TzbConstants.pageId, flowNodePageOptimizeRelation.getToPageId());
						jsonFlow.put(TzbConstants.pageName, flowNodePageOptimizeRelation.getToPageName());
						jsonFlow.put(TzbConstants.pageRouter, flowNodePageOptimizeRelation.getToPageRouter());

						jsonObject.getJSONObject(TzbConstants.flowJson).getJSONArray(TzbConstants.flowset).remove(jsonIndex);
						jsonObject.getJSONObject(TzbConstants.flowJson).getJSONArray(TzbConstants.flowset).add(jsonIndex, jsonFlow);
					}
				}

			}

			jsonIndex++;
		}
		return jsonObject.getJSONObject(TzbConstants.flowJson);
	}

	@Override
	public String processOptimization(JSONObject jsonObject) {
		log.info("processOptimization start --->");
		log.info("processOptimization params: {}", jsonObject.toString());
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			JSONObject jsonObj = this.nodeOptimization(jsonObject);
			jsonObj = this.pageOptimization(jsonObj);
			map = ResultUtil.resultMap(CodeUtil.CODE_200.getName(), CodeUtil.CODE_200.getCode(), jsonObj);
		} catch (Exception e) {
			map = ResultUtil.resultMap(CodeUtil.CODE_200.getName(), CodeUtil.CODE_200.getCode(), jsonObject);
			log.error("processOptimization error: ", e);
		}
		String returnJSONStr = JSONObject.fromObject(map).toString();
		log.info("processOptimization return: {}", returnJSONStr);
		log.info("processOptimization end --->");
		return returnJSONStr;
	}

}
